﻿using System;
using System.Collections.Generic;
using Baseballdata.Context;
using Baseballdata.Data;
using System.Data.Linq;
using System.Linq;
using System.Text;
namespace Batters
{
    class Batters
    {
        private double getStd(List<double> dbList)
        {
            double avg = dbList.Average();
            double sumOfDev = 0;
            foreach (double value in dbList)
            {
                sumOfDev += (value) * (value);
            }
            double soda = sumOfDev / dbList.Count;
            return Math.Sqrt(soda - (avg * avg));
        }
        private double getMean(List<double> dbLst)
        {
            double mean = 0;
            foreach (double average in dbLst)
            {
                mean += average;
            }
            mean /= dbLst.Count;
            return mean;
        }
        
        private double getZScore(double stats, double mean, double std)
        {

            double zScore = 0;
            zScore = ((stats-mean)/std);

            return zScore;
        }
        static void Main(string[] args)
        {
            Batters newPrg = new Batters();
            List<double> hofDbls = new List<double>();
            List<double> hofTrips = new List<double>();
            List<double> hofHits = new List<double>();
            List<double> hofABS = new List<double>();
            List<double> hofHRS = new List<double>();
            List<double> hofRuns = new List<double>();
            List<double> hofRBIS = new List<double>();
            List<double> hofSBS= new List<double>();
            List<double> hofAVG = new List<double>();
            List<double> nwDls = new List<double>();
            double zValueDoubles = 0;
            double zValueTrips = 0;
            double zValueHits = 0;
            double zValueABS = 0;
            double zValueHRS = 0;
            double zValueRuns = 0;
            double zValueRBIS = 0;
            double zValueSBS = 0;
            double zValueAVG = 0;
            string hofPlayerid = null;
            Dictionary<string, double> zscore = new Dictionary<string, double>();
            Console.WriteLine("Enter Id: ");
            hofPlayerid = Console.ReadLine();
            BaseballdataDataContext db = new BaseballdataDataContext();
            var results = from hof in db.HallOfFames
                          where hof.hofID==hofPlayerid 
                          select hof;
            Console.WriteLine("start printing-------------");
            foreach (var q in results)
            {
                Console.WriteLine("{0},{1}", q.hofID.Trim(),q.inducted);
            }
            Console.WriteLine("end printing--------");
            //Start
            DateTime startTime = DateTime.Now;
            var rslt = from hof in db.HallOfFames
                       where hof.inducted.Equals('Y') && hof.category == "Player"
                       //&& hof.hofID == hofPlayerid
                       select hof;
            
            Console.WriteLine("start for only Y---------");
            var count = 0;
            foreach (var q in rslt)
            {
                var fld = (from f in db.Fieldings
                                join m in db.Masters on f.playerID equals m.playerID
                                where (!f.POS.Equals('P') && q.hofID == m.hofID)
                                orderby f.playerID ascending                                
                                group f by f.playerID into field
                                where field.Count() > 10
                                select new
                                {
                                    Id = field.Key
                                }).Distinct();
                foreach (var n in fld)
                {   
                    var master = from b in db.Battings
                                 join m in db.Masters on b.playerID equals m.playerID
                                 where (n.Id == b.playerID)
                                 group b by b.playerID into batting
                                 //&& hof.hofID == hofPlayerid
                                 select new
                                 {
                                     Id = batting.Key,
                                     Doubles = batting.Average(i => i._2B),
                                     Triples = batting.Average(i2 => i2._3B),
                                     Hits = batting.Average(i3 => i3.H),
                                     AB = batting.Average(i8 => i8.AB),
                                     HomeRuns = batting.Average(i4 => i4.HR),
                                     Runs = batting.Average(i5 => i5.R),
                                     RBI = batting.Average(i6 => i6.RBI),
                                     StolenBases = batting.Average(i7 => i7.SB),
                                     Avg = (Double)(((Double)batting.Sum(i9 => i9.H)) / ((Double)batting.Sum(i10 => i10.AB)))                               
                                 };
                    foreach (var s in master)   
                    {
                        hofDbls.Add((double)s.Doubles);
                        hofTrips.Add((double)s.Triples);
                        hofHits.Add((double)s.Hits);
                        hofABS.Add((double)s.AB);
                        hofHRS.Add((double)s.HomeRuns);
                        hofRuns.Add((double)s.Runs);
                        hofRBIS.Add((double)s.RBI);
                        hofSBS.Add((double)s.StolenBases);
                        hofAVG.Add((double)s.Avg);
                        count++;
                    }
                }
            }
            
            //Console.WriteLine("{0},{1},{2},{3},{4}", totalDoubles, totalTriples, totalHits, totalHomeRuns, count);
            double hofDblsStd = newPrg.getStd(hofDbls);
            double hofDblsMean = newPrg.getMean(hofDbls);

            double hofTripsStd = newPrg.getStd(hofTrips);
            double hofTripsMean = newPrg.getMean(hofTrips);

            double hofHitsStd = newPrg.getStd(hofHits);
            double hofHitsMean = newPrg.getMean(hofHits);

            double hofABSStd = newPrg.getStd(hofABS);
            double hofABSMean = newPrg.getMean(hofABS);

            double hofHRSStd = newPrg.getStd(hofHRS);
            double hofHRSMean = newPrg.getMean(hofHRS);

            double hofRunsStd = newPrg.getStd(hofRuns);
            double hofRunsMean = newPrg.getMean(hofRuns);

            double hofRBISStd = newPrg.getStd(hofRBIS);
            double hofRBISMean = newPrg.getMean(hofRBIS);

            double hofSBSStd = newPrg.getStd(hofSBS);
            double hofSBSMean = newPrg.getMean(hofSBS);

            double hofAVGStd = newPrg.getStd(hofAVG);
            double hofAVGMean = newPrg.getMean(hofAVG);
            //End
            DateTime endTime = DateTime.Now;
            Console.WriteLine("{0} {1}", hofDblsStd, hofDblsMean);
            Console.WriteLine("Total records {0}", count);
            Console.WriteLine("end printing--------");
            //Start time
            DateTime start = DateTime.Now;
            var plyList = from bttr in db.Battings
                          where (from fldgs in db.Fieldings
                                 where !fldgs.POS.Equals('P')
                                 group fldgs by fldgs.playerID into fld
                                 where fld.Count() > 10
                                 select fld.Key).Contains(bttr.playerID)
                                  &&
                                  !(from mst in db.Masters
                                    join hoff in db.HallOfFames on mst.hofID equals hoff.hofID
                                    select mst.hofID).Contains(bttr.playerID)
                          orderby bttr.playerID
                          group bttr by bttr.playerID into batter
                          select new
                          {
                              ID = batter.Key
                          };


            Console.WriteLine("start for new ID");
            double ctagain = 0;
            foreach (var qq in plyList)
            {
                var mastrB = from b in db.Battings
                             join m in db.Masters on b.playerID equals m.playerID
                             where (qq.ID == b.playerID)
                             group b by b.playerID into batting
                             select new
                             {
                                 Id = batting.Key,
                                 Doubles = batting.Average(i => i._2B),
                                 Triples = batting.Average(i2 => i2._3B),
                                 Hits = batting.Average(i3 => i3.H),
                                 AB = batting.Average(i8 => i8.AB),
                                 HomeRuns = batting.Average(i4 => i4.HR),
                                 Runs = batting.Average(i5 => i5.R),
                                 RBI = batting.Average(i6 => i6.RBI),
                                 StolenBases = batting.Average(i7 => i7.SB),
                                 Avg = (Double)(((Double)batting.Sum(i9 => i9.H)) / ((Double)batting.Sum(i10 => i10.AB)))
                             };
                foreach (var sq in mastrB)
                {
                    zValueDoubles = newPrg.getZScore((Double)sq.Doubles, hofDblsMean, hofDblsStd);
                    zValueTrips = newPrg.getZScore((Double)sq.Triples, hofTripsMean, hofTripsStd);
                    zValueHits = newPrg.getZScore((Double)sq.Hits, hofHitsMean, hofHitsStd);
                    zValueABS = newPrg.getZScore((Double)sq.AB, hofABSMean, hofABSStd);
                    zValueHRS = newPrg.getZScore((Double)sq.HomeRuns, hofHRSMean, hofHRSStd);
                    zValueRuns = newPrg.getZScore((Double)sq.Runs, hofRunsMean, hofRunsStd);
                    zValueRBIS = newPrg.getZScore((Double)sq.RBI, hofRBISMean, hofRBISStd);
                    zValueSBS = newPrg.getZScore((Double)sq.StolenBases, hofSBSMean, hofSBSStd);
                    zValueAVG = newPrg.getZScore((Double)sq.Avg, hofAVGMean, hofAVGStd);
                    double totals = ((zValueDoubles + zValueTrips + zValueHits + zValueABS + zValueHRS + zValueRuns + zValueRBIS + zValueSBS + zValueAVG) / 9);
                    zscore.Add(sq.Id, totals);
                    ctagain++;
                   
                }
            }
            //endtime
            DateTime end = DateTime.Now;
            TimeSpan duration1 = endTime - startTime;
            TimeSpan duration2 = end - start;
            Console.WriteLine("Time to calculate std and mean for hall of fame players {0}, {1}", duration1.TotalMinutes, duration1.TotalSeconds);
            Console.WriteLine("Time to calculate zscore for all batters {0}, {1}", duration2.TotalMinutes, duration2.TotalSeconds);
            Console.WriteLine("ct for new Id {0}", ctagain);



            Console.ReadLine();

            //results.ToList();
        }
    }
}
